package aufgabe_2_test.try02;

import static akka.actor.Actors.remote;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.math.BigInteger;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.JScrollPane;
import javax.swing.JButton;

import akka.actor.ActorRef;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class Gui_Master extends JFrame {

	private static final long serialVersionUID = 644608277599503735L;
	private JPanel contentPane;
	private JTextField textField_N;
	private JTable worker_table;
	private WorkersTableModel tableM;
	private ResultTableModel resTableM;
	private JTextField txtLocalhost;
	private JLabel lblHostname;
	private JTextField textField_port;
	private JLabel label;
	private JLabel lblPort;
	private JButton btnStart;
	private JTextField textField_amount;
	private JTable table_results;
	private static Gui_Master frame;
	/**
	 * reference to ONE Master
	 */
	private ActorRef master;
	/**
	 * represent the source list of worker information
	 */
	private ArrayList<WorkerObject> workerList;
	/**
	 * represent the list of calculations results
	 */
	private ArrayList<ResultObject> resultList;


	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					 frame = new Gui_Master();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Gui_Master() {
		resultList = new ArrayList<ResultObject>();
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 801, 561);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);
		
		textField_N = new JTextField();
		textField_N.setText("8806715679");
		textField_N.setBounds(38, 60, 200, 20);
		contentPane.add(textField_N);
		textField_N.setColumns(10);
		
		JLabel lblZuFaktorisierndeZahl = new JLabel("Zu faktorisiernde Zahl");
		lblZuFaktorisierndeZahl.setBounds(37, 46, 155, 14);
		contentPane.add(lblZuFaktorisierndeZahl);
		
		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(12, 232, 315, 221);
		contentPane.add(scrollPane);
		
		worker_table = new JTable();
		scrollPane.setViewportView(worker_table);
		
		workerList = new ArrayList<WorkerObject>();
		tableM= new WorkersTableModel(workerList);
		worker_table.setModel(tableM);
		
		txtLocalhost = new JTextField();
		txtLocalhost.setText("localhost");
		txtLocalhost.setBounds(38, 133, 86, 20);
		contentPane.add(txtLocalhost);
		txtLocalhost.setColumns(10);
		
		lblHostname = new JLabel("Hostname");
		lblHostname.setBounds(38, 120, 58, 14);
		contentPane.add(lblHostname);
		
		textField_port = new JTextField();
		textField_port.setText("2000");
		textField_port.setToolTipText("");
		textField_port.setBounds(146, 133, 86, 20);
		contentPane.add(textField_port);
		textField_port.setColumns(10);
		
		label = new JLabel(":");
		label.setBounds(134, 136, 13, 14);
		contentPane.add(label);
		
		lblPort = new JLabel("Port");
		lblPort.setBounds(146, 120, 46, 14);
		contentPane.add(lblPort);
		
		JButton btnWorkerHinzufgen = new JButton("Worker hinzuf\u00FCgen");
		btnWorkerHinzufgen.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				//checks port range
				int port = getIntFromString(textField_port.getText());
				if(port < 0  || port < 1024 || port > ( (1 << 16) - 1) ){
					return;
				}
				
				//checks amount worker parsing
				int amount = getIntFromString(textField_amount.getText() );
				if(amount < 0){
					return;
				}
				
				addToList( new WorkerObject(txtLocalhost.getText(), port, amount) );
				tableM.fireTableDataChanged();
			}
		});
		btnWorkerHinzufgen.setBounds(390, 132, 146, 23);
		contentPane.add(btnWorkerHinzufgen);
		
		btnStart = new JButton("Start");
		btnStart.addActionListener(new ActionListener() {
			/**
			 * starts a new calculation process
			 */
			public void actionPerformed(ActionEvent e) {
				RhoRequestMaster reqM;
				
				if(!textField_N.getText().equals("")){
					try{
						BigInteger n = new BigInteger(textField_N.getText());
						reqM = new RhoRequestMaster(n, workerList);
					}catch(NumberFormatException ne){
						JOptionPane.showMessageDialog(frame,
							    "N ist keine Zahl, eventuell sind Leerzeihen enthalten",
							    "Parsing Error",
							    JOptionPane.ERROR_MESSAGE);
						return;
					}
					
					
					//avoid more than one Master
					if(master == null){
						master = remote().actorFor(Master.class.getName(), "lab23", 1999);						
					}
					master.tell(reqM);
					
				}
			}
		});
		btnStart.setBounds(12, 455, 89, 23);
		contentPane.add(btnStart);
		
		textField_amount = new JTextField();
		textField_amount.setText("3");
		textField_amount.setBounds(250, 132, 116, 22);
		contentPane.add(textField_amount);
		textField_amount.setColumns(10);
		
		JLabel lblAnzhalWorker = new JLabel("Anzahl Worker");
		lblAnzhalWorker.setBounds(251, 119, 98, 16);
		contentPane.add(lblAnzhalWorker);
		
		JScrollPane scrollPane_results = new JScrollPane();
		scrollPane_results.setBounds(360, 232, 411, 221);
		contentPane.add(scrollPane_results);
		
		table_results = new JTable();
		resTableM = new ResultTableModel(resultList);
		table_results.setModel(resTableM);
		scrollPane_results.setViewportView(table_results);
		
		JLabel lblErgebnisse = new JLabel("Ergebnistabelle");
		lblErgebnisse.setBounds(360, 203, 129, 16);
		contentPane.add(lblErgebnisse);
		
		JLabel lblWorkertabelle = new JLabel("Workertabelle");
		lblWorkertabelle.setBounds(12, 203, 84, 16);
		contentPane.add(lblWorkertabelle);
		
		JButton btnGewhlteHostsAus = new JButton("markierten Host entfernen");
		btnGewhlteHostsAus.addActionListener(new ActionListener() {
			/**
			 * delete and refresh table
			 */
			public void actionPerformed(ActionEvent arg0) {				
				workerList.remove(worker_table.getSelectedRow());
				tableM.fireTableDataChanged();
				
			}
		});
		btnGewhlteHostsAus.setBounds(111, 455, 216, 23);
		contentPane.add(btnGewhlteHostsAus);
	}
	
	/**
	 * own method to parse String for N-Input/Port/Amount workers
	 * @param s String that will convert to a integer
	 * @return greater 0 if okay, -1 if String cannot be converted
	 */
	private int getIntFromString(String s){
		int val = 0;
		
		try{
			val = Integer.parseInt(s);
			
		}catch(NumberFormatException nfe){
			val = -1;
		}
		
		return val;
	}
	
	/**
	 * only adds worker with different hostname
	 * @param wO the object will be added to the list
	 */
	private void addToList(WorkerObject wO){
		for (WorkerObject elem : workerList) {
			if(elem.equals(wO)){
				return;
			}
		}
		workerList.add(wO);
	}
	
	/**
	 * adds a result from Master
	 * @param n, given figure for calculation 
	 * @param fac, the factors
	 * @param sumT, sum of all calculations
	 * @param wallT, wall time
	 */
	public void addAResult(BigInteger n, String fac, String sumT, String wallT){
		resultList.add( new ResultObject(n, fac, sumT, wallT) );
		resTableM.fireTableDataChanged();
	}
	
	/**
	 * adds a result from Master
	 * @param resu, result object from Master
	 */
	public void addAResult(ResultObject resu){
		resultList.add( resu );
		resTableM.fireTableDataChanged();
	}

	/**
	 * update the cpu time in resultObject
	 * @param sum_CpuTime, increments the actual cpu time
	 */
	public void updateTable(String sum_CpuTime) {
		ResultObject rs = resultList.get(resultList.size()-1);
		rs.setSum_cpuTime(""+sum_CpuTime);
		resTableM.fireTableDataChanged();
	}
}
